﻿using System;
using System.ComponentModel;
using System.Threading;

namespace ParallelLib
{
    /// <summary>
    /// 轮询器
    /// </summary>
    public class Poller
    {
        private readonly ManualResetEvent PauseEvent = new ManualResetEvent(false);

        private readonly ManualResetEvent StopEvent = new ManualResetEvent(false);

        /// <summary>
        /// 空闲休眠时间
        /// </summary>
        public int IdleTime { get; set; }

        /// <summary>
        /// 工作函数
        /// </summary>
        public Action MainWork { get; set; }

        /// <summary>
        /// 线程状态
        /// </summary>
        public PollerState State { get; private set; }

        /// <summary>
        /// 线程名
        /// </summary>
        public string ThreadName { get; set; }

        /// <summary>
        /// 轮询工作间隔
        /// </summary>
        public int WorkInternal { get; set; }

        private Thread MainThread { get; set; }

        /// <summary>
        ///
        /// </summary>
        /// <param name="threadName">轮询线程名</param>
        /// <param name="workInternal">轮询工作间隔</param>
        /// <param name="idleTime">轮询空闲间隔</param>
        public Poller(string threadName = "<NULL POLLER>", int workInternal = 100, int idleTime = 500)
        {
            MainThread = new Thread(Work);
            ThreadName = threadName;
            WorkInternal = workInternal;
            IdleTime = idleTime;
            State = PollerState.UnStarted;
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="threadName">轮询线程名</param>
        /// <param name="workInternal">轮询工作间隔</param>
        /// <param name="idleTime">轮询空闲间隔</param>
        public Poller(Action work,string threadName = "<NULL POLLER>", int workInternal = 100, int idleTime = 500)
        {
            MainWork = work;
            MainThread = new Thread(Work);
            ThreadName = threadName;
            WorkInternal = workInternal;
            IdleTime = idleTime;
            State = PollerState.UnStarted;
        }

        /// <summary>
        /// 继续
        /// </summary>
        public void Continue()
        {
            if (State != PollerState.Paused)
                return;
            PauseEvent.Set();
            State = PollerState.Running;
        }

        /// <summary>
        /// 释放
        /// </summary>
        public void Dispose()
        {
            PauseEvent.Set();
            StopEvent.Set();
            int k = 25;
            while (MainThread.IsAlive)
            {
                k--;
                Thread.Sleep(10);
                if (k < 0)
                {
                    try
                    {
#pragma warning disable SYSLIB0006 // 类型或成员已过时
                        MainThread.Abort();
#pragma warning restore SYSLIB0006 // 类型或成员已过时
                    }
                    catch (Exception)
                    {
                        var msg = string.Format("{0}:线程强制终止,TID:{1}", ThreadName, MainThread.ManagedThreadId);
                        System.Diagnostics.Trace.WriteLine(msg);
                    }
                }
            }
            PauseEvent.Dispose();
            StopEvent.Dispose();
            State = PollerState.Disposed;
        }

        /// <summary>
        /// 暂停
        /// </summary>
        public void Pause()
        {
            if (State != PollerState.Running)
                return;
            PauseEvent.Reset();
            State = PollerState.Paused;
        }

        /// <summary>
        /// 开始
        /// </summary>
        public void Start()
        {
            if (MainThread == null
                || (MainThread.ThreadState & ThreadState.Stopped) != 0
                || (MainThread.ThreadState & ThreadState.StopRequested) != 0
                || (MainThread.ThreadState & ThreadState.AbortRequested) != 0
                || (MainThread.ThreadState & ThreadState.Aborted) != 0)
            {
                MainThread = new Thread(Work) { IsBackground = true, Name = ThreadName };
            }
            if ((MainThread.ThreadState & ThreadState.Unstarted) != 0)
            {
                MainThread.Start();
            }
            else if ((MainThread.ThreadState & ThreadState.Suspended) != 0)
            {
#pragma warning disable 0618
                MainThread.Resume();
#pragma warning restore 0618
            }
            PauseEvent.Set();
            StopEvent.Reset();
            State = PollerState.Running;
        }

        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            PauseEvent.Set();
            StopEvent.Set();
            State = PollerState.Stoped;
        }

        private void StateChanged(PollerState state)
        {
            State = state;
        }

        /// <summary>
        /// 工作线程执行函数
        /// </summary>
        private void Work()
        {
            while (true)
            {
                try
                {
                    if (StopEvent.WaitOne(0))
                    {
                        StateChanged(PollerState.Exited);
                        break;
                    }
                    if (PauseEvent.WaitOne(-1))
                    {
                        if (MainWork != null)
                        {
                            MainWork.Invoke();
                        }
                        else
                        {
                            Thread.Sleep(IdleTime);
                        }
                    }
                    else
                    {
                        Thread.Sleep(WorkInternal);
                    }
                }
                catch (ThreadAbortException)
                {
                    StateChanged(PollerState.Exited);
                    //线程终止
                    break;
                }
                catch (Exception ex)
                {
                    var msg = string.Format("{0}:轮询异常,Msg:{1},Stack:{2}", ThreadName, ex.Message, ex.StackTrace);
                    System.Diagnostics.Trace.WriteLine(msg);
                    Thread.Sleep(WorkInternal);
                }
            }
        }

        #region Poller状态枚举定义

        /// <summary>
        /// Poller状态
        /// </summary>
        public enum PollerState
        {
            /// <summary>
            /// 未启动
            /// </summary>
            [Description("未启动")]
            UnStarted = 0,

            /// <summary>
            /// 运行中
            /// </summary>
            [Description("运行中")]
            Running = 1,

            /// <summary>
            /// 已暂停
            /// </summary>
            [Description("已暂停")]
            Paused = 2,

            /// <summary>
            /// 已停止
            /// </summary>
            [Description("已停止")]
            Stoped = 3,

            /// <summary>
            /// 已退出
            /// </summary>
            [Description("已退出")]
            Exited = 4,

            /// <summary>
            /// 已释放
            /// </summary>
            [Description("已释放")]
            Disposed = 5,
        }

        #endregion Poller状态枚举定义
    }
}